Tutorial 6: Manipulação de Dados com Tidyverse

Introdução.

Nas nossas duas primeiras semanas de aula, focamos em uma introdução básica ao R e a comunicar nossos resultados usando relatórios dinâmicos e de alta qualidade via RMarkdown.

Pelas próximas três semanas, focaremos em três habilidades centrais para nosso trabalha enquanto cientista social computacional: i) manipulação de banco de dados, b) visualização de dados, e c) programação funcional.

Para aprender estas três habilidades, faremos uso dos pacotes do tidyverse.

Tidyverse

O tidyverse é uma família de pacotes em R. Estes pacotes foram e são desenvolvidos de forma integrada, compartilhando uma mesma filosofia de design, gramática e estruturas de dados subjacentes. Portanto, se você aprender um, os outros pacotes ficarão mais fáceis.

O objetivo do tidyverse é prover um conjunto integrado de ferramentas para o uso do R como linguagem em Ciência de Dados. O que signifca que os pacotes do tidyverse cobrem temas como manipulação de dados, visualização, preparação, modelagem, limpeza, entre outros. Estes são os principais pacotes do tidyverse:

  • dplyr: para manipulação de dados.

  • ggplot2: para visualização de dados.

  • tidyr: para preparar seus dados para análise.

  • purrr: para otimizar seu código e para programação funcional.

  • readr: para abrir e organizar os dados.

  • stringr: para manipulação de objetos de texto.

  • forcats: para manipulação da classe fatores.

Porque devo usar o tidyverse ?

Você não deve usar o tidyverse. Porém, há diversas vantagens em usar os pacotes do tidyverse para sua dinâmica de trabalho em R. Algumas delas são:

  • O tidyverse facilita substancialmente as tarefas de análise de dados quando comparado com códigos do R básico.

  • Aumenta substancialmente quão legível seu código parece.

  • Manipulação, visualização e modelagem estão integradas no tidyverse.

  • É amplamente utilizado na comunidade de R. Portanto, provavelmente você precisa aprender para ler códigos no futuro.

No tutorial de hoje, faremos uma breve introdução ao tidyverse e em seguida focaremos no uso do do dplyr para manipulação de bancos de dados.

Entrando no Tidyverse

Instalação.

O primeiro passo é instalarmos o tidyverse. Com um comando, estamos instalando dezenas de pacotes em nosso R.

install.packages("tidyverse")
library(tidyverse)

Tibbles.

O objeto fundamental do tidyverse são bancos de dados. Sendo um pacote desenvolvido para ciência de dados, manipulação e visualização, todos os pacotes do tidyverse são desenvolvidos para funcionar com formatos básicos de banco de dados.

O tidyverse usa objetos chamados de “tibbles” para definir seus bancos de dados ao invés do tradicional data.frame que aprendemos semana passada. Tibbles são exatamente iguais a banco de dados em sua estrutura básica, no entanto, tibbles possuem alguns ajustes para facilitar sua aplicabilidade.

Criando Tibbles.

# Classe do Banco de Dados mtcars
class(mtcars)
## [1] "data.frame"
# Converte para tibbles
mtcars_tib <- as_tibble(mtcars)
mtcars_tib
## # A tibble: 32 x 11
##      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
##    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
##  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
##  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
##  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
##  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
##  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
##  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
##  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
##  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
## 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
## # … with 22 more rows

Pipe.

knitr::include_graphics("figs/pipe.jpg")

O uso de pipes %>% é uma peça fundamental no funcionamento dos pacotes do tidyverse, em particular para processos de manipulação de bancos de dados.

O %>%permite a você concatenar, conectar em cadeias as funções do seu código. Esta conexão faz com que nossos códigos se tornem mais intuitivos e fáceis de serem lidos e interpretados.

Para entendermos a utilidade dos pipes, é bom perceber primeiro como o R conecta operações distintas.

O R funciona de dentro para fora:

# R
x <- c(1:10)
round(exp(sqrt(mean(x))), 1)
## [1] 10.4

o %>% conecta estas operações em ordem lógica:

x %>%
  mean() %>%
  sqrt() %>%
  exp() %>%
  round(1) 
## [1] 10.4

Notas importantes sobre os pipes.

1. Os pipes sempre devem ser usados para conectar funções e seus outputs.

# Não rode este código.
x %>%
  funcao1(arg1=x) %>%
  funcao2(arg=output_da_funcao1)

Exemplo:

sample(1:1000, 500, replace=TRUE) %>%
  density() %>% # funcao 1.
  plot() # função 2. 

2. O input sempre pode ser omitido, ou representados pelo atalho .

sample(1:1000, 500, replace=TRUE) %>%
  density(.) %>% # funcao 1.
  plot(.) # função 2. 

3. Os resultados do pipe não são salvos imediatamente. Você precisa atribuir à um novo objeto.

grafico <- sample(1:1000, 500, replace=TRUE) %>%
              density(.) %>% # funcao 1.
              plot(.) # função 2. 

Desafio.

Reescreva o código abaixo utilizando o %>%.

library(tidyverse)

x <- "cpdoc"
x <- str_to_upper(x)
x <- str_c(x, "-FGV")
x <- str_to_title(x)
x
## [1] "Cpdoc-Fgv"

Manipulação de dados com dplyr.

A partir deste ponto, focaremos no pacote dplyr para manipular e transformar banco de dados. Vamos utilizar dados eleitorais do Brasil, extraídos a partir do pacote cepespR, para tornar nosso aprendizado mais intuitivo

Dados Eleitorais: cepespR

if (!require("devtools")) install.packages("devtools")
devtools::install_github("Cepesp-Fgv/cepesp-r") 
library(cepespR)
library(tidyverse)

pres_rio <- get_votes(year = 2018, 
                         position = "Presidente", 
                         regional_aggregation = "Municipio", 
                         state="RJ") %>%
                  as_tibble()

Informações básicas

glimpse(pres_rio)
## Rows: 1,374
## Columns: 19
## $ ANO_ELEICAO       <int> 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 201…
## $ SIGLA_UE          <chr> "BR", "BR", "BR", "BR", "BR", "BR", "BR", "BR", "BR…
## $ NUM_TURNO         <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ DESCRICAO_ELEICAO <chr> "ELEIÇÃO GERAL FEDERAL 2018", "ELEIÇÃO GERAL FEDERA…
## $ CODIGO_CARGO      <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
## $ DESCRICAO_CARGO   <chr> "PRESIDENTE", "PRESIDENTE", "PRESIDENTE", "PRESIDEN…
## $ NUMERO_CANDIDATO  <int> 12, 13, 15, 16, 17, 18, 19, 27, 30, 45, 50, 51, 54,…
## $ CODIGO_MACRO      <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, …
## $ NOME_MACRO        <chr> "Sudeste", "Sudeste", "Sudeste", "Sudeste", "Sudest…
## $ UF                <chr> "RJ", "RJ", "RJ", "RJ", "RJ", "RJ", "RJ", "RJ", "RJ…
## $ NOME_UF           <chr> "Rio de Janeiro", "Rio de Janeiro", "Rio de Janeiro…
## $ CODIGO_MESO       <int> 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, …
## $ NOME_MESO         <chr> "Sul Fluminense", "Sul Fluminense", "Sul Fluminense…
## $ CODIGO_MICRO      <int> 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,…
## $ NOME_MICRO        <chr> "Baía da Ilha Grande", "Baía da Ilha Grande", "Baía…
## $ COD_MUN_TSE       <int> 58017, 58017, 58017, 58017, 58017, 58017, 58017, 58…
## $ COD_MUN_IBGE      <int> 3300100, 3300100, 3300100, 3300100, 3300100, 330010…
## $ NOME_MUNICIPIO    <chr> "Angra dos Reis", "Angra dos Reis", "Angra dos Reis…
## $ QTDE_VOTOS        <int> 8696, 13204, 565, 34, 59499, 662, 349, 32, 998, 190…

Introdução ao Dplyr.

O dplyr é um dos pacotes mais populares em R. Sua lógica é simples: suas funções fazem exatamente o que seus nomes descrevem (verb based language). Seu uso torna nosso código mais intuitivo de seguir, entender e ler. Veja alguns exemplos.

Estas são as funções mais úteis do dplyr:

  • select(): selecionar colunas.

  • filter(): filtrar o banco de dados por linhas.

  • mutate(): criar novas variáveis e alterar existentes.

  • arrange(): ordenar o banco de dados.

  • group_by(): agrupar e fazer análiser nos subgrupos.

  • summarize(): sumariza os dados por subgroups.

Algumas outras funções menos utilizadas:

  • count(): contar número de observações por subgrupos.

  • distinct(): eliminar repetições.

  • n(): conta quantas observações há em dados agrupados.

  • sample_n(): Selecion n amostras do seu banco de dadosl

  • glimpse(): Fornece um sumário dos seus dados.

  • top_n(): Seleciona por linhas de acordo com o rank das variáveis.

  • slice(): filtra seu banco de dados por posições.

Todas essas funções seguem as mesmas características:

  • O input é sempre um banco de dados.

  • O banco de dados é sempre o primeiro argumento.

  • Os argumentos seguintes acessão colunas dos bancos de dados diretamente, sem aspas.

  • O output é sempre um novo banco de dados.

Select: Seleciona Colunas.

Uso Básico.

pres_rio %>% # Dados
  select(ANO_ELEICAO, SIGLA_UE, NOME_MUNICIPIO, COD_MUN_IBGE) # colunas
## # A tibble: 1,374 x 4
##    ANO_ELEICAO SIGLA_UE NOME_MUNICIPIO COD_MUN_IBGE
##          <int> <chr>    <chr>                 <int>
##  1        2018 BR       Angra dos Reis      3300100
##  2        2018 BR       Angra dos Reis      3300100
##  3        2018 BR       Angra dos Reis      3300100
##  4        2018 BR       Angra dos Reis      3300100
##  5        2018 BR       Angra dos Reis      3300100
##  6        2018 BR       Angra dos Reis      3300100
##  7        2018 BR       Angra dos Reis      3300100
##  8        2018 BR       Angra dos Reis      3300100
##  9        2018 BR       Angra dos Reis      3300100
## 10        2018 BR       Angra dos Reis      3300100
## # … with 1,364 more rows

Reordenando Colunas

pres_rio %>% # Dados
  # seleciona colunas
  select(QTDE_VOTOS, ANO_ELEICAO, SIGLA_UE, 
         NOME_MUNICIPIO, COD_MUN_IBGE) # colunas
## # A tibble: 1,374 x 5
##    QTDE_VOTOS ANO_ELEICAO SIGLA_UE NOME_MUNICIPIO COD_MUN_IBGE
##         <int>       <int> <chr>    <chr>                 <int>
##  1       8696        2018 BR       Angra dos Reis      3300100
##  2      13204        2018 BR       Angra dos Reis      3300100
##  3        565        2018 BR       Angra dos Reis      3300100
##  4         34        2018 BR       Angra dos Reis      3300100
##  5      59499        2018 BR       Angra dos Reis      3300100
##  6        662        2018 BR       Angra dos Reis      3300100
##  7        349        2018 BR       Angra dos Reis      3300100
##  8         32        2018 BR       Angra dos Reis      3300100
##  9        998        2018 BR       Angra dos Reis      3300100
## 10       1909        2018 BR       Angra dos Reis      3300100
## # … with 1,364 more rows

Renomeando Colunas

pres_rio %>% 
  # seleciona colunas com novos nomes. 
  select(votos=QTDE_VOTOS, 
         ano=ANO_ELEICAO, 
         pais=SIGLA_UE, 
         mun=NOME_MUNICIPIO, 
         cod=COD_MUN_IBGE) # colunas
## # A tibble: 1,374 x 5
##    votos   ano pais  mun                cod
##    <int> <int> <chr> <chr>            <int>
##  1  8696  2018 BR    Angra dos Reis 3300100
##  2 13204  2018 BR    Angra dos Reis 3300100
##  3   565  2018 BR    Angra dos Reis 3300100
##  4    34  2018 BR    Angra dos Reis 3300100
##  5 59499  2018 BR    Angra dos Reis 3300100
##  6   662  2018 BR    Angra dos Reis 3300100
##  7   349  2018 BR    Angra dos Reis 3300100
##  8    32  2018 BR    Angra dos Reis 3300100
##  9   998  2018 BR    Angra dos Reis 3300100
## 10  1909  2018 BR    Angra dos Reis 3300100
## # … with 1,364 more rows

Salvando Novo Banco.

rio_reduzido <- pres_rio %>% # Dados
                  # seleciona colunas com novos nomes. 
                  select(votos=QTDE_VOTOS, 
                         ano=ANO_ELEICAO, 
                         pais=SIGLA_UE, 
                         mun=NOME_MUNICIPIO, 
                         cod=COD_MUN_IBGE) # colunas

Outros Atalhos para Uso do Select.

  • contains() - Extrai colunas que contêm determinado texto.

  • starts_with() - Extrai colunas que inicia com determinado texto.

  • ends_with() - Extrai colunas que termina com determinado texto.

  • everything() - Extrai todas as colunas restantes.

Exemplos

pres_rio %>%
  # seleciona colunas onde NOME aparece
  select(contains("NOME"))
## # A tibble: 1,374 x 5
##    NOME_MACRO NOME_UF        NOME_MESO      NOME_MICRO          NOME_MUNICIPIO
##    <chr>      <chr>          <chr>          <chr>               <chr>         
##  1 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  2 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  3 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  4 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  5 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  6 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  7 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  8 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
##  9 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
## 10 Sudeste    Rio de Janeiro Sul Fluminense Baía da Ilha Grande Angra dos Reis
## # … with 1,364 more rows
pres_rio %>%
  # seleciona colunas que terminam com UF e 
  # todas as outras colunas restantes
  select(ends_with("UF"), everything())
## # A tibble: 1,374 x 19
##    UF    NOME_UF ANO_ELEICAO SIGLA_UE NUM_TURNO DESCRICAO_ELEIC… CODIGO_CARGO
##    <chr> <chr>         <int> <chr>        <int> <chr>                   <int>
##  1 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  2 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  3 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  4 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  5 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  6 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  7 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  8 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
##  9 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
## 10 RJ    Rio de…        2018 BR               1 ELEIÇÃO GERAL F…            1
## # … with 1,364 more rows, and 12 more variables: DESCRICAO_CARGO <chr>,
## #   NUMERO_CANDIDATO <int>, CODIGO_MACRO <int>, NOME_MACRO <chr>,
## #   CODIGO_MESO <int>, NOME_MESO <chr>, CODIGO_MICRO <int>, NOME_MICRO <chr>,
## #   COD_MUN_TSE <int>, COD_MUN_IBGE <int>, NOME_MUNICIPIO <chr>,
## #   QTDE_VOTOS <int>

Filter: Filtra Linhas por Condições Lógicas.

Uso Básico.

  filter(data, coluna=="a")
pres_rio %>%
  # filtra casos ondem partido igual a 17.
  filter(NUMERO_CANDIDATO==17) %>%
  # seleciona
  select(DESCRICAO_CARGO, NUMERO_CANDIDATO, QTDE_VOTOS, NOME_MUNICIPIO)
## # A tibble: 184 x 4
##    DESCRICAO_CARGO NUMERO_CANDIDATO QTDE_VOTOS NOME_MUNICIPIO    
##    <chr>                      <int>      <int> <chr>             
##  1 PRESIDENTE                    17      59499 Angra dos Reis    
##  2 PRESIDENTE                    17       4366 Aperibé           
##  3 PRESIDENTE                    17      44108 Araruama          
##  4 PRESIDENTE                    17       3816 Areal             
##  5 PRESIDENTE                    17      13028 Armação dos Búzios
##  6 PRESIDENTE                    17      13342 Arraial do Cabo   
##  7 PRESIDENTE                    17      27178 Barra do Piraí    
##  8 PRESIDENTE                    17      55972 Barra Mansa       
##  9 PRESIDENTE                    17     138676 Belford Roxo      
## 10 PRESIDENTE                    17       8077 Bom Jardim        
## # … with 174 more rows

Multiplas Condições

pres_rio %>%
  # filtra usando or
  filter(NUMERO_CANDIDATO==17 | NUMERO_CANDIDATO==13, # or
  #filtra usando and
         NOME_MUNICIPIO=="Rio de Janeiro") %>% # and
  #selecion
  select(DESCRICAO_CARGO, NUMERO_CANDIDATO, QTDE_VOTOS, NOME_MUNICIPIO)
## # A tibble: 4 x 4
##   DESCRICAO_CARGO NUMERO_CANDIDATO QTDE_VOTOS NOME_MUNICIPIO
##   <chr>                      <int>      <int> <chr>         
## 1 PRESIDENTE                    13     398033 Rio de Janeiro
## 2 PRESIDENTE                    17    1930657 Rio de Janeiro
## 3 PRESIDENTE                    13    1105393 Rio de Janeiro
## 4 PRESIDENTE                    17    2179896 Rio de Janeiro

Arrange: Ordena Linhas por Colunas.

Uso Básico:

arrange(data, coluna)
pres_rio %>%
  # filtra pelas linhas
  filter(NUMERO_CANDIDATO==13) %>% 
  # seleciona
  select(DESCRICAO_CARGO, NUMERO_CANDIDATO,
         QTDE_VOTOS, NOME_MUNICIPIO) %>%
  # ordena de forma crescente
  arrange(QTDE_VOTOS)
## # A tibble: 184 x 4
##    DESCRICAO_CARGO NUMERO_CANDIDATO QTDE_VOTOS NOME_MUNICIPIO               
##    <chr>                      <int>      <int> <chr>                        
##  1 PRESIDENTE                    13        830 São José do Vale do Rio Preto
##  2 PRESIDENTE                    13       1111 Areal                        
##  3 PRESIDENTE                    13       1115 Santa Maria Madalena         
##  4 PRESIDENTE                    13       1129 Aperibé                      
##  5 PRESIDENTE                    13       1152 São José de Ubá              
##  6 PRESIDENTE                    13       1224 Macuco                       
##  7 PRESIDENTE                    13       1241 Varre-Sai                    
##  8 PRESIDENTE                    13       1342 Italva                       
##  9 PRESIDENTE                    13       1448 São Sebastião do Alto        
## 10 PRESIDENTE                    13       1455 Duas Barras                  
## # … with 174 more rows

Decrescente

pres_rio %>%
  # filtra pelas linhas
  filter(NUMERO_CANDIDATO==13) %>% 
  # seleciona variáveis
  select(DESCRICAO_CARGO, NUMERO_CANDIDATO, 
         QTDE_VOTOS, NOME_MUNICIPIO) %>%
  # ordena em valores descrecentes
  arrange(desc(QTDE_VOTOS))
## # A tibble: 184 x 4
##    DESCRICAO_CARGO NUMERO_CANDIDATO QTDE_VOTOS NOME_MUNICIPIO       
##    <chr>                      <int>      <int> <chr>                
##  1 PRESIDENTE                    13    1105393 Rio de Janeiro       
##  2 PRESIDENTE                    13     398033 Rio de Janeiro       
##  3 PRESIDENTE                    13     149075 São Gonçalo          
##  4 PRESIDENTE                    13     136240 Duque de Caxias      
##  5 PRESIDENTE                    13     110820 Nova Iguaçu          
##  6 PRESIDENTE                    13     105606 Niterói              
##  7 PRESIDENTE                    13      80858 São Gonçalo          
##  8 PRESIDENTE                    13      79838 Campos dos Goytacazes
##  9 PRESIDENTE                    13      77504 Duque de Caxias      
## 10 PRESIDENTE                    13      70499 São João de Meriti   
## # … with 174 more rows

Mutate: Adiciona uma nova coluna.

Uso Básico:

mutate(data, nome_nova_coluna=valores_nova_coluna)
pres_rio %>%
  # cria variável com estado e cidade
  mutate(estado_cidade=paste(NOME_MUNICIPIO, "-", NOME_UF)) %>%
  #seleciona para visualizar
  select(NOME_MUNICIPIO, NOME_UF, estado_cidade)
## # A tibble: 1,374 x 3
##    NOME_MUNICIPIO NOME_UF        estado_cidade                  
##    <chr>          <chr>          <chr>                          
##  1 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  2 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  3 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  4 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  5 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  6 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  7 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  8 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
##  9 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
## 10 Angra dos Reis Rio de Janeiro Angra dos Reis - Rio de Janeiro
## # … with 1,364 more rows

Condicionais

pres_rio %>%
  # cria variável usando condicionais
  mutate(estado_sigla=ifelse(NOME_UF=="Rio de Janeiro", "RJ", NA), 
  # concatena nova variável com cidade
         estado_cidade=paste(estado_sigla, "-", NOME_MUNICIPIO)) %>%
  #selectiona
  select(NOME_UF, NOME_MUNICIPIO, estado_sigla, everything())
## # A tibble: 1,374 x 21
##    NOME_UF NOME_MUNICIPIO estado_sigla ANO_ELEICAO SIGLA_UE NUM_TURNO
##    <chr>   <chr>          <chr>              <int> <chr>        <int>
##  1 Rio de… Angra dos Reis RJ                  2018 BR               1
##  2 Rio de… Angra dos Reis RJ                  2018 BR               1
##  3 Rio de… Angra dos Reis RJ                  2018 BR               1
##  4 Rio de… Angra dos Reis RJ                  2018 BR               1
##  5 Rio de… Angra dos Reis RJ                  2018 BR               1
##  6 Rio de… Angra dos Reis RJ                  2018 BR               1
##  7 Rio de… Angra dos Reis RJ                  2018 BR               1
##  8 Rio de… Angra dos Reis RJ                  2018 BR               1
##  9 Rio de… Angra dos Reis RJ                  2018 BR               1
## 10 Rio de… Angra dos Reis RJ                  2018 BR               1
## # … with 1,364 more rows, and 15 more variables: DESCRICAO_ELEICAO <chr>,
## #   CODIGO_CARGO <int>, DESCRICAO_CARGO <chr>, NUMERO_CANDIDATO <int>,
## #   CODIGO_MACRO <int>, NOME_MACRO <chr>, UF <chr>, CODIGO_MESO <int>,
## #   NOME_MESO <chr>, CODIGO_MICRO <int>, NOME_MICRO <chr>, COD_MUN_TSE <int>,
## #   COD_MUN_IBGE <int>, QTDE_VOTOS <int>, estado_cidade <chr>

Operações Matemáticas.

pres_rio %>%
  # log dos votos
  mutate(log_votos=log(QTDE_VOTOS)) %>%
  # seleciona
  select(QTDE_VOTOS, log_votos)
## # A tibble: 1,374 x 2
##    QTDE_VOTOS log_votos
##         <int>     <dbl>
##  1       8696      9.07
##  2      13204      9.49
##  3        565      6.34
##  4         34      3.53
##  5      59499     11.0 
##  6        662      6.50
##  7        349      5.86
##  8         32      3.47
##  9        998      6.91
## 10       1909      7.55
## # … with 1,364 more rows

Group_by + Summarize.

Uma tarefa muito comum quando manipulamos bancos de dados é calcular valores para determinados subgroups. Por exemplo:

  • Qual a votação total dos candidatos a presidencia no Estado do Rio de Janeiro ?

  • Qual o total de votos por município?

  • Em qual micro-região Jair Bolsonaro saiu com maior vantagem?

Para responder esta perguntas, faremos uso da função group_by + summarize.

Group_by

O primeiro passo é agrupar de acordo com a variável de nosso interesse.

pres_rio %>%
  # agrupando por candidato presidencial
  group_by(NUMERO_CANDIDATO) 
## # A tibble: 1,374 x 19
## # Groups:   NUMERO_CANDIDATO [13]
##    ANO_ELEICAO SIGLA_UE NUM_TURNO DESCRICAO_ELEIC… CODIGO_CARGO DESCRICAO_CARGO
##          <int> <chr>        <int> <chr>                   <int> <chr>          
##  1        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  2        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  3        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  4        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  5        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  6        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  7        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  8        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  9        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
## 10        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
## # … with 1,364 more rows, and 13 more variables: NUMERO_CANDIDATO <int>,
## #   CODIGO_MACRO <int>, NOME_MACRO <chr>, UF <chr>, NOME_UF <chr>,
## #   CODIGO_MESO <int>, NOME_MESO <chr>, CODIGO_MICRO <int>, NOME_MICRO <chr>,
## #   COD_MUN_TSE <int>, COD_MUN_IBGE <int>, NOME_MUNICIPIO <chr>,
## #   QTDE_VOTOS <int>

group_by somente agrupa seu banco. É como se criassêmos diversos mini-bancos de dados no background do R. A partir disso, podemos usar summarize para calcular valores de nosso interesse neste subgrupos.

Summarize.

Uso básico:

summarize(dados_agrupados, nome_nova_variavel=valores_calculados)
pres_rio %>%
  # Somente primeiro turno 
  filter(NUM_TURNO==1) %>%
  # agrupando por candidato presidencial
  group_by(NUMERO_CANDIDATO) %>%
  # Somando os votos em todo o estado.
  summarise(voto_estado=sum(QTDE_VOTOS)) %>%
  # Ordena
  arrange(desc(voto_estado))
## # A tibble: 13 x 2
##    NUMERO_CANDIDATO voto_estado
##               <int>       <int>
##  1               17     5107735
##  2               12     1300292
##  3               13     1255425
##  4               51      211444
##  5               45      208325
##  6               30      139208
##  7               18      130794
##  8               15       77333
##  9               50       57846
## 10               19       41544
## 11               16        6005
## 12               27        4636
## 13               54        2806

Perceba: o summarize transforma múltiplas linhas em uma para cada subgrupo

Mais Exemplos

Quem ganhou no Rio de Janeiro no Segundo Turno?

pres_rio %>%
  # Somente primeiro turno 
  filter(NUM_TURNO==2) %>%
  # agrupando por candidato presidencial
  group_by(NUMERO_CANDIDATO) %>%
  # Somando os votos em todo o estado.
  summarise(voto_estado=sum(QTDE_VOTOS)) %>%
  # Ordena
  arrange(desc(voto_estado))
## # A tibble: 2 x 2
##   NUMERO_CANDIDATO voto_estado
##              <int>       <int>
## 1               17     5669059
## 2               13     2673386

Total de Votos por Município

pres_rio %>%
  # Somente primeiro turno 
  filter(NUM_TURNO==1) %>%
  # agrupando por candidato presidencial
  group_by(NOME_MUNICIPIO) %>%
  # Somando os votos em todo o estado.
  summarise(voto_mun=sum(QTDE_VOTOS)) 
## # A tibble: 92 x 2
##    NOME_MUNICIPIO     voto_mun
##  * <chr>                 <int>
##  1 Angra dos Reis        88316
##  2 Aperibé                6680
##  3 Araruama              64481
##  4 Areal                  6921
##  5 Armação dos Búzios    19979
##  6 Arraial do Cabo       20133
##  7 Barra do Piraí        48942
##  8 Barra Mansa           96980
##  9 Belford Roxo         226785
## 10 Bom Jardim            14090
## # … with 82 more rows

Votos por Meso-Região

pres_rio %>%
  # Somente primeiro turno 
  filter(NUM_TURNO==1) %>%
  # agrupando por candidato presidencial
  group_by(NUMERO_CANDIDATO, NOME_MESO) %>%
  # soma de votos por município
  summarise(voto_media=mean(QTDE_VOTOS), 
            voto_min=min(QTDE_VOTOS), 
            voto_max=max(QTDE_VOTOS))
## # A tibble: 78 x 5
## # Groups:   NUMERO_CANDIDATO [13]
##    NUMERO_CANDIDATO NOME_MESO                       voto_media voto_min voto_max
##               <int> <chr>                                <dbl>    <int>    <int>
##  1               12 Baixadas                             4769.     1157    13478
##  2               12 Centro Fluminense                    2558       403    16254
##  3               12 Metropolitana do Rio de Janeiro     35187.      702   645674
##  4               12 Noroeste Fluminense                  1393.      296     4684
##  5               12 Norte Fluminense                     6909.      798    33042
##  6               12 Sul Fluminense                       5412.      812    23860
##  7               13 Baixadas                             4409.     1574    10310
##  8               13 Centro Fluminense                    2954.     1111    10664
##  9               13 Metropolitana do Rio de Janeiro     31261.      830   398033
## 10               13 Noroeste Fluminense                  2789.     1129     8209
## # … with 68 more rows

Outras funções úteis.

Count: Contar por grupos.

pres_rio %>%
  # Quantas entradas para cada número candidato?
  count(NUMERO_CANDIDATO)
## # A tibble: 13 x 2
##    NUMERO_CANDIDATO     n
##  *            <int> <int>
##  1               12    92
##  2               13   184
##  3               15    92
##  4               16    91
##  5               17   184
##  6               18    92
##  7               19    92
##  8               27    92
##  9               30    92
## 10               45    92
## 11               50    92
## 12               51    92
## 13               54    87

Slice: Selecionar por posição das linhas.

pres_rio %>%
  slice(1:10)
## # A tibble: 10 x 19
##    ANO_ELEICAO SIGLA_UE NUM_TURNO DESCRICAO_ELEIC… CODIGO_CARGO DESCRICAO_CARGO
##          <int> <chr>        <int> <chr>                   <int> <chr>          
##  1        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  2        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  3        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  4        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  5        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  6        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  7        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  8        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
##  9        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
## 10        2018 BR               1 ELEIÇÃO GERAL F…            1 PRESIDENTE     
## # … with 13 more variables: NUMERO_CANDIDATO <int>, CODIGO_MACRO <int>,
## #   NOME_MACRO <chr>, UF <chr>, NOME_UF <chr>, CODIGO_MESO <int>,
## #   NOME_MESO <chr>, CODIGO_MICRO <int>, NOME_MICRO <chr>, COD_MUN_TSE <int>,
## #   COD_MUN_IBGE <int>, NOME_MUNICIPIO <chr>, QTDE_VOTOS <int>

rowid_to_column() : criar id para linhas

pres_rio %>% 
  rowid_to_column() %>%
  select(1:5)
## # A tibble: 1,374 x 5
##    rowid ANO_ELEICAO SIGLA_UE NUM_TURNO DESCRICAO_ELEICAO         
##    <int>       <int> <chr>        <int> <chr>                     
##  1     1        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  2     2        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  3     3        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  4     4        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  5     5        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  6     6        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  7     7        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  8     8        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
##  9     9        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
## 10    10        2018 BR               1 ELEIÇÃO GERAL FEDERAL 2018
## # … with 1,364 more rows

Desafio

Mutate x Summarize.

Qual a diferença entre as funções mutate and summarize ? Porque os dois exemplos abaixo geram resultados distintos?

# Exemplo: Mutate
pres_rio %>%
  # Somente primeiro turno 
  filter(NUM_TURNO==1) %>%
  # group
## Error: <text>:7:0: unexpected end of input
## 5:   # group
## 6: 
##   ^

Praticando:

Abre o banco de dados de candidatos a deputado federal no Rio de Janeiro.

dep_rio <- get_candidates(year=2018,
                          position="Federal Deputy") %>%
           as_tibble()

Responda:

  1. Qual partido elegeu mais deputados? (3 linhas)

Dica: data %>% filter(COD_SIT_TOT_TURNO==2 | COD_SIT_TOT_TURNO==3) filtra somente os eleitos.

  1. Qual candidato gastou mais recursos ? (2-3 linhas)

  2. Qual valor médio declarado de gastos de campanha de acordo com o gênero dos candidatos? (3 linhas)

Conectando Bancos de Dados com Dplyr.

Raramente, você encontrará um banco de dados onde todas as informações da sua pesquisa estão contidas e prontas para serem analisadas.

Na maioria dos casos, e por boas razões, bancos de dados possuem informações distintas, e os pesquisadores precisamos conectá-los com vistas a construir o material necessário para suas análises.

Este tipo de dados conectados a partir de várias tabelas são chamados de dados relacionais. dados eleitorais no Brasil providos pelo TSE vem em pedaços distintos de informação, que podem a depender dos objetivos de sua análise ser conectados. De forma mais concreta, estes são alguns exemplos de bancos disponíveis no TSE

  • Candidatos: arrecadação, nome, profissão, etc.

  • Votação: dados de votação por município, zonal, seção eleitoral.

  • Eleitorado: perfil dos eleitores registrados no nível da zona eleitoral.

Chaves (keys)

Ainda nos casos dos bancos de dados do TSE, por exemplo, usando o número do candidato e a unidade eleitoral é possível conectar os bancos de candidatos e votação, ou usando o número da zona eleitoral por município, conectar votação e eleitorado.

Estas variáveis capazes de conectar bancos de dados são chamadas chaves. Estas chaves são:

  • Completas. Nunca tenha missing values nas suas chaves.

  • Únicas: cada observação deve possuir uma chave distinta. Evite sempre duplicações.

Joins

Inspirado na linguaguem SQL, o dplyr possui um conjunto de funções com foco em conectar bancos de dados distintos.

Vamos criar dois bancos bem simples para entendermos como estes joins funcionam.

data1 <- tibble(nome=c("A", "B", "C"), 
                value=c(10, 20, 30)) 
data2 <- tibble(nome=c("A", "D", "C"), 
                value2=c(10, 50, 30))

left_join()

left_join(data1, data2)
## # A tibble: 3 x 3
##   nome  value value2
##   <chr> <dbl>  <dbl>
## 1 A        10     10
## 2 B        20     NA
## 3 C        30     30

inner_join()

inner_join(data1, data2)
## # A tibble: 2 x 3
##   nome  value value2
##   <chr> <dbl>  <dbl>
## 1 A        10     10
## 2 C        30     30

full_join()

full_join(data1, data2)
## # A tibble: 4 x 3
##   nome  value value2
##   <chr> <dbl>  <dbl>
## 1 A        10     10
## 2 B        20     NA
## 3 C        30     30
## 4 D        NA     50

Chaves Distintas?

Em inúmeros casos, os bancos que precisamos conectar terá nomes diferentes. Este problema é fácil de resolver. É preciso adicionar o argumento dos nomes, e ajudar as funções joins a fazerem seu serviço.

data3 <- data2 %>%
          # alterando o nome
          select(chave=nome, everything())

# Join

left_join(data1, data3, 
          by=c("nome"="chave")) # adicione argumento by.
## # A tibble: 3 x 3
##   nome  value value2
##   <chr> <dbl>  <dbl>
## 1 A        10     10
## 2 B        20     NA
## 3 C        30     30

Desafio

Abre os bancos de dados de candidatos e votos do TSE. Faça um join entre eles, e salve o banco de dados.

  • Quantas linhas este novo banco de dados possuí?

  • Explique o número de linhas.

# Banco Candidatos
candidatos <- get_candidates(year=2018, position="President") %>% 
                as_tibble()

# Banco Votos
votos <- get_votes(year = 2018, position="President", state="RJ") %>%
            as_tibble()
# Join? 

Concatenando Bancos de Dados

Além de juntar bancos de dados usando chaves, podemos concatecar bancos verticalmente (pelas linhas) ou horizontalmente (pelas colunas).

bind_rows: por linhas

bind_rows(data1, data2)
## # A tibble: 6 x 3
##   nome  value value2
##   <chr> <dbl>  <dbl>
## 1 A        10     NA
## 2 B        20     NA
## 3 C        30     NA
## 4 A        NA     10
## 5 D        NA     50
## 6 C        NA     30

Note: ao conectar por linha, as colunas precisam ter os mesmos nomes. Caso não, você adicionará uma nova variável ao resultado final.

bind_cols: por colunas

bind_cols(data1, data2)
## # A tibble: 3 x 4
##   nome...1 value nome...3 value2
##   <chr>    <dbl> <chr>     <dbl>
## 1 A           10 A            10
## 2 B           20 D            50
## 3 C           30 C            30

Note: ao conectar por coluna, as linhas precisam ter tamanho igual.